package com.ardf.service.impl;

import com.alibaba.excel.EasyExcel;
import com.ardf.common.EntityConstants;
import com.ardf.entity.AthleteProject;
import com.ardf.entity.Batch;
import com.ardf.entity.Project;
import com.ardf.entity.Signin;
import com.ardf.entity.dto.DownloadSignInDto;
import com.ardf.entity.dto.SignInSearchAllDto;
import com.ardf.entity.dto.SignInTableDto;
import com.ardf.entity.vo.SignInUpdateOneVo;
import com.ardf.mapper.AthleteProjectMapper;
import com.ardf.mapper.BatchMapper;
import com.ardf.mapper.ProjectMapper;
import com.ardf.mapper.SigninMapper;
import com.ardf.service.ISigninService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ShiYunHao
 * @since 2025-01-06
 */
@Service
public class SigninServiceImpl extends ServiceImpl<SigninMapper, Signin> implements ISigninService {

    private final SigninMapper signinMapper;
    private final ProjectMapper projectMapper;
    private final AthleteProjectMapper athleteProjectMapper;
    private final BatchMapper batchMapper;

    public SigninServiceImpl(SigninMapper signinMapper, ProjectMapper projectMapper,
                             AthleteProjectMapper athleteProjectMapper, BatchMapper batchMapper) {
        this.signinMapper = signinMapper;
        this.projectMapper = projectMapper;
        this.athleteProjectMapper = athleteProjectMapper;
        this.batchMapper = batchMapper;
    }

    @Override
    public Page<SignInTableDto> searchAll(Integer pageSize, Integer pageNum, Long competitionId, String searchAll) {
        boolean flag = true;
        Long projectId = null;
        if (searchAll != null) {
            String[] splits = searchAll.split("-");
            Map<String, Byte> typeMap = Map.of("快速", EntityConstants.PROJECT_TYPE_FAST,
                    "中距离", EntityConstants.PROJECT_TYPE_MEDIUM,
                    "短距离", EntityConstants.PROJECT_TYPE_SHORT,
                    "阳光测向", EntityConstants.PROJECT_TYPE_SUNLIGHT,
                    "标准距离", EntityConstants.PROJECT_TYPE_STANDARD);
            Map<String, Byte> frequencyMap = Map.of("2m", EntityConstants.PROJECT_FREQUENCY_2m,
                    "80m", EntityConstants.PROJECT_FREQUENCY_80m);
            Map<String, Byte> categoryMap = Map.of("个人", EntityConstants.PROJECT_CATEGORY_PERSON,
                    "接力", EntityConstants.PROJECT_CATEGORY_RELAY);
            //校验是否是搜索项目名
            Byte type = null;
            Byte frequency = null;
            Byte category = null;
            if (splits.length == 3) {
                type = typeMap.get(splits[0]);
                frequency = frequencyMap.get(splits[1]);
                category = categoryMap.get(splits[2]);
                if (type != null && frequency != null && category != null) {
                    flag = false;
                    Project project = projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                            .eq(Project::getType, type)
                            .eq(Project::getCategory, category)
                            .eq(Project::getFrequency, frequency)
                            .eq(Project::getCompetitionId, competitionId));
                    projectId = project.getId();
                }
            }
        }

        Page<SignInSearchAllDto> page = new Page<>(pageNum, pageSize);
        Page<SignInSearchAllDto> athleteSearchAllDtos;
        if (flag) {//除了项目名以外的搜索
            athleteSearchAllDtos = signinMapper.searchAll(page, competitionId, searchAll);
        } else {//搜索项目名
            athleteSearchAllDtos = signinMapper.searchAllByProjectId(page, projectId);
        }
        List<SignInTableDto> records = athleteSearchAllDtos.getRecords().stream().map(athleteSearchAllDto -> {
            SignInTableDto athleteTableDto = new SignInTableDto();
            BeanUtils.copyProperties(athleteSearchAllDto, athleteTableDto);
            Map<Byte, String> projectType = Map.of(EntityConstants.PROJECT_TYPE_FAST, "快速",
                    EntityConstants.PROJECT_TYPE_MEDIUM, "中距离",
                    EntityConstants.PROJECT_TYPE_SHORT, "短距离",
                    EntityConstants.PROJECT_TYPE_SUNLIGHT, "阳光测向",
                    EntityConstants.PROJECT_TYPE_STANDARD, "标准距离");
            Map<Byte, String> projectFrequency = Map.of(EntityConstants.PROJECT_FREQUENCY_2m, "2m",
                    EntityConstants.PROJECT_FREQUENCY_80m, "80m");
            Map<Byte, String> projectCategory = Map.of(EntityConstants.PROJECT_CATEGORY_PERSON, "个人",
                    EntityConstants.PROJECT_CATEGORY_RELAY, "接力");
            List<String> list = athleteSearchAllDto.getProjects().stream().map(project -> projectType.get(project.getType()) + "-" +
                    projectFrequency.get(project.getFrequency()) + "-" +
                    projectCategory.get(project.getCategory())).toList();
            athleteTableDto.setProjectNames(list);
            return athleteTableDto;
        }).toList();
        Page<SignInTableDto> athleteTableDtoPage = new Page<>(pageNum, pageSize);
        athleteTableDtoPage.setRecords(records);
        athleteTableDtoPage.setTotal(page.getTotal());
        athleteTableDtoPage.setCurrent(page.getCurrent());
        return athleteTableDtoPage;
    }

    @Override
    public void download(HttpServletResponse response, Long competitionId) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("签到表", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        List<DownloadSignInDto> list = signinMapper.getAll(competitionId);
        Map<Byte, String> projectType = Map.of(EntityConstants.PROJECT_TYPE_FAST, "快速",
                EntityConstants.PROJECT_TYPE_MEDIUM, "中距离",
                EntityConstants.PROJECT_TYPE_SHORT, "短距离",
                EntityConstants.PROJECT_TYPE_SUNLIGHT, "阳光测向",
                EntityConstants.PROJECT_TYPE_STANDARD, "标准距离");
        Map<Byte, String> projectFrequency = Map.of(EntityConstants.PROJECT_FREQUENCY_2m, "2m",
                EntityConstants.PROJECT_FREQUENCY_80m, "80m");
        Map<Byte, String> projectCategory = Map.of(EntityConstants.PROJECT_CATEGORY_PERSON, "个人",
                EntityConstants.PROJECT_CATEGORY_RELAY, "接力");
        for (DownloadSignInDto downloadSignInDto : list) {
            List<String> list1 = downloadSignInDto.getProjects().stream().map(project -> projectType.get(project.getType()) + "-"
                    + projectFrequency.get(project.getFrequency()) + "-" +
                    projectCategory.get(project.getCategory())).toList();
            StringJoiner stringJoiner = new StringJoiner(",");
            for (String s : list1) {
                stringJoiner.add(s);
            }
            downloadSignInDto.setProjectNames(stringJoiner.toString());
        }
        EasyExcel.write(response.getOutputStream(), DownloadSignInDto.class).sheet("表格1").doWrite(list);
    }

    @Override
    @Transactional
    public void updateOne(SignInUpdateOneVo signInUpdateOneVo) {
        Signin signin = new Signin();
        BeanUtils.copyProperties(signInUpdateOneVo, signin);
        signinMapper.updateById(signin);
        Signin signin1 = signinMapper.selectById(signInUpdateOneVo.getId());
        if (EntityConstants.SIGNIN_STATUS_YES.equals(signin.getStatus())) {//添加签到表
            List<AthleteProject> athleteProjects = athleteProjectMapper.selectList(new LambdaQueryWrapper<AthleteProject>()
                    .eq(AthleteProject::getAthleteId, signin1.getAthleteId()));
            List<Batch> batches = athleteProjects.stream().map(athleteProject -> {
                Batch batch = new Batch();
                batch.setAthleteId(athleteProject.getAthleteId());
                batch.setProjectId(athleteProject.getProjectId());
                return batch;
            }).toList();
            batchMapper.insert(batches);
        } else {//删除签到表
            batchMapper.delete(new LambdaQueryWrapper<Batch>()
                    .eq(Batch::getAthleteId, signin1.getAthleteId()));
        }
    }

    @Override
    @Transactional
    public void updateBatch(List<Long> ids) {
        List<Signin> signins = new ArrayList<>();
        for (Long id : ids) {
            Signin signin = new Signin();
            signin.setId(id);
            signin.setStatus(EntityConstants.SIGNIN_STATUS_YES);
            signins.add(signin);
        }
        signinMapper.updateById(signins);
        //添加签到表
        List<Signin> signins1 = signinMapper.selectByIds(ids);
        List<Long> athleteIds = signins1.stream().map(Signin::getAthleteId).toList();
        for (Long athleteId : athleteIds) {
            Long batchCount = batchMapper.selectCount(new LambdaQueryWrapper<Batch>()
                    .eq(Batch::getAthleteId, athleteId));
            if(batchCount==null||batchCount==0){
                List<AthleteProject> athleteProjects = athleteProjectMapper.selectList(new LambdaQueryWrapper<AthleteProject>()
                        .eq(AthleteProject::getAthleteId, athleteId));
                List<Batch> batches = athleteProjects.stream().map(athleteProject -> {
                    Batch batch = new Batch();
                    batch.setAthleteId(athleteProject.getAthleteId());
                    batch.setProjectId(athleteProject.getProjectId());
                    return batch;
                }).toList();
                batchMapper.insert(batches);
            }
        }
    }
}
